package com.scholarship.modules.admin.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.scholarship.common.dto.ResultListDto;
import com.scholarship.common.entity.RedisKeys;
import com.scholarship.common.utils.*;
import com.scholarship.modules.admin.dto.*;
import com.scholarship.modules.admin.entity.*;
import com.scholarship.modules.admin.exce.UpdateFailedException;
import com.scholarship.modules.admin.mapper.*;
import com.scholarship.modules.admin.service.StudentInfoListService;
import com.scholarship.modules.admin.utils.RankingUtil;
import com.scholarship.modules.login.entity.Role;
import com.scholarship.modules.login.entity.User;
import com.scholarship.modules.login.mapper.LRoleMapper;
import com.scholarship.modules.login.mapper.LUserMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @Author Z.J.H
 * @create 2021/4/14 14:23
 */
@Service
public class StudentInfoListServiceImpl implements StudentInfoListService {

    @Autowired
    private LUserMapper lUserMapper;

    @Autowired
    private LRoleMapper lRoleMapper;

    @Autowired
    private AUserInfoMapper aUserInfoMapper;

    @Autowired
    private ARewardApplicationMapper aRewardApplicationMapper;

    @Autowired
    private ARewardFeedbackMapper aRewardFeedbackMapper;

    @Autowired
    private ACommonMapper aCommonMapper;

    @Autowired
    private ARewardTypeDetailMapper aRewardTypeDetailMapper;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 获取学生管理列表查询条件
     * @return
     * @throws Exception
     */
    @Override
    public Map<String, List<String>> getStudentQuery() throws Exception {

        String redisKey = RedisKeys.STUDENT_QUERY.toString();
        //查询缓存
        Map<String, List<String>> map = (Map<String, List<String>>) redisTemplate.opsForValue().get(redisKey);
        //双重检测锁
        if(map == null) {
            synchronized (this) {
                //再次查询缓存
                map = (Map<String, List<String>>) redisTemplate.opsForValue().get(redisKey);
                //缓存为空，则从数据库获取数据
                if(map == null) {
                    List<String> years = new ArrayList<>();
                    years.add("所有学年");
                    years.addAll(aUserInfoMapper.listYear());

                    List<String> majors = new ArrayList<>();
                    majors.add("所有专业");
                    majors.addAll(aUserInfoMapper.listMajor());

                    List<String> stuClasses = new ArrayList<>();
                    stuClasses.add("所有班级");
                    stuClasses.addAll(aUserInfoMapper.listStuClass());

                    map = new HashMap<>();
                    map.put("year",years);
                    map.put("major",majors);
                    map.put("stuClass",stuClasses);
                    //查询数据放入缓存
                    redisTemplate.opsForValue().set(redisKey,map,30L, TimeUnit.SECONDS);
                }
            }
        }

        return map;
    }

    /**
     * 查询所有学生信息
     * @return
     * @throws Exception
     */
    @Override
    public ResultListDto<StudentInfoListDto> listAllStudentInfo(Integer pageNum, Integer pageSize) throws Exception {
        //使用PageHelper实现分页
        PageHelper.startPage(pageNum,pageSize);
        List<StudentInfoListDto> list = aUserInfoMapper.listStudentInfoListDto();
        PageInfo<StudentInfoListDto> pageInfo = new PageInfo<>(list);

        return new ResultListDto<StudentInfoListDto>(pageInfo.getTotal(),pageInfo.getList());
    }

    /**
     * 根据查询条件查询学生信息
     * @param query
     * @return
     * @throws Exception
     */
    @Override
    public ResultListDto<StudentInfoListDto> listStudentInfoByQuery(Integer pageNum, Integer pageSize, StudentQueryDto query) throws Exception {
        //使用PageHelper实现分页
        PageHelper.startPage(pageNum,pageSize);
        List<StudentInfoListDto> list = aUserInfoMapper.listStudentInfoListDtoByQuery(query);
        PageInfo<StudentInfoListDto> pageInfo = new PageInfo<>(list);

        return new ResultListDto<StudentInfoListDto>(pageInfo.getTotal(),pageInfo.getList());
    }

    /**
     * 根据搜索查询学生信息
     * @param searchStr
     * @return
     * @throws Exception
     */
    @Override
    public ResultListDto<StudentInfoListDto> listStudentInfoBySearch(Integer pageNum,Integer pageSize,String searchStr) throws Exception {
        //使用PageHelper实现分页
        PageHelper.startPage(pageNum,pageSize);
        List<StudentInfoListDto> list = aUserInfoMapper.listStudentInfoListDtoBySearch(searchStr);
        PageInfo<StudentInfoListDto> pageInfo = new PageInfo<>(list);

        return new ResultListDto<StudentInfoListDto>(pageInfo.getTotal(),pageInfo.getList());
    }

    /**
     * 修改学生用户密码
     * @param userId
     * @param newPwd
     * @throws Exception
     */
    @Override
    public void changeUserPwd(String userId, String newPwd) throws Exception {
        String saltPwd = CommonUtil.encryptPassword(newPwd,userId);

        lUserMapper.updatePasswordByUserId(userId,saltPwd);
    }

    /**
     * 添加学生信息
     * @param userInfo
     * @return  学生信息是否存在
     *
     * @throws Exception
     */
    @Override
    public Boolean addStudentInfo(UserInfo userInfo) throws Exception {
        if(aUserInfoMapper.getCountByUserId(userInfo.getUserId()) > 0) {
            return false;
        }
        //获取导入年份
        Calendar calendar = Calendar.getInstance();
        String importYear = String.valueOf(calendar.get(Calendar.YEAR));

        userInfo.setImportYear(importYear);
        userInfo.setTotalScore(.0);
        userInfo.setTotalRank(0);
        String useId = userInfo.getUserId();

        //将学号作为初始密码进行MD5盐值加密
        String password = CommonUtil.encryptPassword(useId,useId);
        //创建账号(1:已启用)
        User user = new User(null,useId,userInfo.getName(),password,1);
        //赋予身份:1学生
        Role role = new Role(useId,1);

        RewardApplication rewardApplication = new RewardApplication();
        rewardApplication.setUserId(useId);
        rewardApplication.setTableId(1);
        rewardApplication.setImportYear(importYear);
        rewardApplication.setScore(userInfo.getScore());
        rewardApplication.setState(1);

        lUserMapper.insertUser(user);
        lRoleMapper.insertRole(role);
        aUserInfoMapper.insertUserInfo(userInfo);
        aRewardApplicationMapper.insertAndUpdateRewardApplication(rewardApplication);

        return true;
    }

    /**
     * 获得学生信息
     * @param userId
     * @return
     * @throws Exception
     */
    @Override
    public UserInfo getStudentInfo(String userId) throws Exception {
        UserInfo userInfo = aUserInfoMapper.getUserInfoByUserId(userId);
        if(StringUtils.isNotBlank(userInfo.getIdCard())) {
            userInfo.setIdCard(new String(Base64.getDecoder().decode(userInfo.getIdCard()), "utf-8"));
        }
        if(StringUtils.isNotBlank(userInfo.getBankCard())) {
            userInfo.setBankCard(new String(Base64.getDecoder().decode(userInfo.getBankCard()), "utf-8"));
        }
        if(StringUtils.isNotBlank(userInfo.getPhone())) {
            userInfo.setPhone(new String(Base64.getDecoder().decode(userInfo.getPhone()), "utf-8"));
        }
        if(StringUtils.isNotBlank(userInfo.getEmail())) {
            userInfo.setEmail(new String(Base64.getDecoder().decode(userInfo.getEmail()), "utf-8"));
        }
        return userInfo;
    }

    /**
     * 更新学生信息
     * @param userInfo
     * @return
     * @throws Exception
     */
    @Override
    public void updateStudentInfo(UserInfo userInfo) throws Exception {
        if(StringUtils.isNotBlank(userInfo.getIdCard())) {
            userInfo.setIdCard(Base64.getEncoder().encodeToString(userInfo.getIdCard().getBytes()));
        }
        if(StringUtils.isNotBlank(userInfo.getBankCard())) {
            userInfo.setBankCard(Base64.getEncoder().encodeToString(userInfo.getBankCard().getBytes()));
        }
        if(StringUtils.isNotBlank(userInfo.getPhone())) {
            userInfo.setPhone(Base64.getEncoder().encodeToString(userInfo.getPhone().getBytes()));
        }
        if(StringUtils.isNotBlank(userInfo.getEmail())) {
            userInfo.setEmail(Base64.getEncoder().encodeToString(userInfo.getEmail().getBytes()));
        }
        aUserInfoMapper.updateUserInfo(userInfo);
    }

    /**
     * 冻结用户账号
     * @param userId
     */
    @Override
    public void frozenUserAccent(String userId) throws UpdateFailedException {
        int flag = lUserMapper.updateStateByUserId(userId,0);
        if(flag == 0) {
            throw new UpdateFailedException("用户已冻结，更新失败");
        }
    }

    /**
     * 激活用户账号
     * @param userId
     */
    @Override
    public void activateUserAccent(String userId) throws UpdateFailedException {
        int flag = lUserMapper.updateStateByUserId(userId,1);
        if(flag == 0) {
            throw new UpdateFailedException("用户已激活，更新失败");
        }
    }

    /**
     * 删除学生全部信息
     * @param userId
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteUser(String userId) throws Exception {
        List<RewardTypeDetail> rewardTypeDetailList = aRewardTypeDetailMapper.listRewardTypeDetail();
        rewardTypeDetailList.forEach(detail -> {
            if(StringUtils.isNotBlank(detail.getTableName())) {
                aCommonMapper.deleteSelectedRewardByUserId(detail.getTableName(),userId);
            }
        });
        aRewardApplicationMapper.deleteRewardApplicationByUserId(userId);
        aRewardFeedbackMapper.deleteRewardFeedbackByUserId(userId);
        aUserInfoMapper.deleteUserInfoByUserId(userId);
        lRoleMapper.deleteRoleByUserId(userId);
        lUserMapper.deleteUserByUserId(userId);
    }

    /**
     * 根据学年专业更新加权平均分排名
     * @param year
     * @param major
     * @throws Exception
     */
    @Override
    public Boolean updateRankByYearMajor(String year, String major) throws Exception {
        List<UserInfo> userInfos = aUserInfoMapper.listUserInfoByYearMajor(year, major);
        if(!userInfos.isEmpty()) {
            userInfos = RankingUtil.rankingScoreInUserInfo(userInfos,false);
            aUserInfoMapper.updateRankByUserInfoList(userInfos);
            return true;
        }
        return false;
    }

    /**
     * 更新全阶段加权平均分排名
     * @throws Exception
     */
    @Override
    public void updateAllRank() throws Exception {
        List<String> years = aUserInfoMapper.listYear();
        List<String> majors = aUserInfoMapper.listMajor();

        for(String year : years) {
            for(String major : majors) {
                //updateRankByYearMajor(year,major);
                List<UserInfo> userInfos = aUserInfoMapper.listUserInfoByYearMajor(year, major);
                if(!userInfos.isEmpty()) {
                    userInfos = RankingUtil.rankingScoreInUserInfo(userInfos,false);
                    aUserInfoMapper.updateRankByUserInfoList(userInfos);
                }
            }
        }
    }
}
